// 创建服务器
const express = require("express");
// cors
const cors = require("cors");
// 创建服务器实例
const app = express();
//字符串解析 false: 解析的是querystring字符串  true: 解析的是application/x-www-form-urlencoded字符串 两种都需要:
app.use(express.urlencoded({ extended: false }));
//json解析
app.use(express.json({ limit: "1mb" })); // 增加请求体大小限制
//跨域
app.use(cors());

const path = require("path");

const joi = require("joi");
const db = require("./db/index");
const { expressjwt: expressJWT } = require("express-jwt");
const config = require("./config");
const jwt = require("jsonwebtoken");

// 导入用户模块
// const userRouter = require("./router/user");
// 注册用户模块
// app.use("/api", userRouter);

// 注册全局的中间件
app.use((req, res, next) => {
  //解释：在res对象上挂载一个cc函数，res.cc()调用时，会默认向客户端响应一个json数据
  res.cc = function (err, status = 1) {
    res.send({
      status,
      message: err instanceof Error ? err.message : err,
    });
  };
  next();
});

// 托管静态资源,浏览器可以直接访问
// http://127.0.0.1:3000/1745237926012-42820879.png
app.use("/uploads", express.static(path.join(__dirname, "public/uploads")));

// websocket  如果你在 Express 中用了如下中间件：这可能会导致 WebSocket 请求被错误地当成普通 HTTP 请求拦截，从而失败！
const http = require("http");
const server = http.createServer(app);
const WebSocket = require("ws");
const wss = new WebSocket.Server({ server });

// 111
wss.on("connection", (ws, req) => {
  console.log("客户端已连接", req.url);
  const token = req.url.replace("/?token=", "");
  const { user } = require("./router_handle/user.js");
  console.log(user, "77777");
  // 去掉Bearer 前缀
  // const token = req.headers.authorization.replace("Bearer ", "");
  console.log(token);
  // if (!token) {
  //   ws.send(JSON.stringify({ error: "No token provided" }));
  //   ws.close();
  //   return;
  // }
  // const decoded = jwt.verify(token, config.jwtSecretKey);
  // if (decoded.username !== user.username) {
  //   return ws.send(JSON.stringify({ error: "Token is invalid" }));
  // }

  const dataChunks = [
    "需求",
    "信息",
    "非常",
    "有限",
    "，",
    "仅",
    "有一个",
    "数字",
    "",
    "1",
    "2",
    "，",
    "这",
    "不足以",
    "让",
  ];
  let i = 0;

  const interval = setInterval(() => {
    if (i < dataChunks.length) {
      ws.send(dataChunks[i]);
      i++;
    } else {
      clearInterval(interval);
      ws.close();
    }
  }, 500); // 每 500ms 发送一段文字
});

let chartData = [5, 20, 36, 10, 10, 20]; // 初始数据

// ws表示连接成功的socket对象 req表示请求对象
// wss.on("connection", (ws, req) => {
//   console.log("客户端已连接");

//   ws.on("message", (message) => {
//     console.log(`Received message => ${message}`);
//     chartData = JSON.parse(message);
//     wss.clients.forEach((client) => {
//       if (client.readyState === WebSocket.OPEN) {
//         client.send(JSON.stringify(chartData));
//         console.log("发送数据给客户端");
//       }
//     });
//   });
//   ws.send(JSON.stringify(chartData));
// });

// 将token放在url上传递，但是需要放在全局的token校验前
app.get("/my/stream", (req, res) => {
  console.log(req.query.token);

  // 去掉Bearer 前缀
  const token = req.query.token;
  console.log(token);
  try {
    const decoded = jwt.verify(token, config.jwtSecretKey);
  } catch (err) {
    res.status(401).end(); // token 无效
    return;
  }

  // 开始推送
  res.setHeader("Content-Type", "text/event-stream");
  res.setHeader("Cache-Control", "no-cache");
  res.setHeader("Connection", "keep-alive");

  const chunks = [
    "需求",
    "信息",
    "非常",
    "有限",
    "，",
    "仅",
    "有一个",
    "数字",
    "",
    "1",
    "2",
    "，",
    "这",
    "不足以",
    "让",
  ];
  let i = 0;

  const interval = setInterval(() => {
    if (i < chunks.length) {
      res.write(`data: ${chunks[i++]}\n\n`);
    } else {
      clearInterval(interval);
      res.end();
    }
  }, 1000);
});

// 发送请求前，验证token api接口不需要验证token  会自动挂载到req.auth对象上
app.use(
  expressJWT({
    secret: config.jwtSecretKey,
    algorithms: ["HS256"],
  }).unless({ path: [/^\/api\//] })
);

// app.use(
//   expressJWT({
//     secret: config.jwtSecretKey,
//     algorithms: ["HS256"],
//   }).unless({ path: [/^\/api\//, /^\/my\/stream$/] })
// );

// SSE 接口
// 1.要么不做token校验,将这个接口在全局token校验中排除掉
// 2.要么在这个接口中做token校验,将这个接口放在全局token校验前面
// app.get("/my/stream", (req, res) => {
//   console.log(req.auth, 100);

//   res.setHeader("Content-Type", "text/event-stream");
//   res.setHeader("Cache-Control", "no-cache");
//   res.setHeader("Connection", "keep-alive");

//   const dataChunks = [
//     "需求",
//     "信息",
//     "非常",
//     "有限",
//     "，",
//     "仅",
//     "有一个",
//     "数字",
//     "",
//     "1",
//     "2",
//     "，",
//     "这",
//     "不足以",
//     "让",
//   ];

//   let i = 0;

//   const interval = setInterval(() => {
//     if (i < dataChunks.length) {
//       res.write(`data: ${dataChunks[i]}\n\n`);
//       i++;
//     } else {
//       clearInterval(interval);
//       res.end();
//     }
//   }, 500); // 每 500ms 推送一段
// });

// 导入用户模块
const userRouter = require("./router/user.js");
app.use("/api", userRouter);
// 导入用户信息模块
const userinfoRouter = require("./router/userinfo.js");
app.use("/my", userinfoRouter);

// 导入文章分类模块
const articlesRouter = require("./router/articles.js");
app.use("/my", articlesRouter);

// 全局错误中间件
app.use((err, req, res, next) => {
  // 数据验证失败
  if (err instanceof joi.ValidationError) return res.cc(err);
  // 捕获身份认证失败的错误
  if (err.name === "UnauthorizedError") return res.cc("身份认证失败！", 401);
  // 未知错误
  res.cc(err);
});

// 监听端口
// app.listen(3000, () => {
//   console.log("服务器启动成功:http://127.0.0.1:3000");
// });

// 端口配置：优先使用环境变量PORT，其次根据运行环境判断
// 3000:生产环境
// 3030:开发环境
const PORT = process.env.PORT || (process.env.NODE_ENV === 'production' ? 3000 : 3030);
server.listen(PORT, () => {
  console.log(`服务器启动成功: http://127.0.0.1:${PORT}`);
});
